package pl.edu.mimuw.irs.rcp.util.dnd;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.TransferData;

public abstract class SerializableTransfer extends ByteArrayTransfer {

	// *** Attributes

	// *** Methods

	@Override
	public void javaToNative(Object object, TransferData transferData) {
		if (object == null || !(object instanceof Serializable[]))
			return;

		if (isSupportedType(transferData)) {
			Serializable[] array = (Serializable[]) object;
			try {
				// write data to a byte array and then ask super to convert to
				// pMedium
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				DataOutputStream writeOut = new DataOutputStream(out);
				for (int i = 0, length = array.length; i < length; i++) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					ObjectOutputStream objectStream = new ObjectOutputStream(baos);
					objectStream.writeObject(array[i]);
					objectStream.close();
					byte[] byteArray = baos.toByteArray();
					
					writeOut.writeInt(byteArray.length);
					writeOut.writeChar('X');
					writeOut.write(byteArray);
				}
				byte[] buffer = out.toByteArray();
				writeOut.close();

				super.javaToNative(buffer, transferData);

			} catch (IOException e) {
			}
		}
	}

	@Override
	public Object nativeToJava(TransferData transferData) {

		if (isSupportedType(transferData)) {

			byte[] buffer = (byte[]) super.nativeToJava(transferData);
			if (buffer == null)
				return null;

			Serializable[] array = new Serializable[0];
			try {
				ByteArrayInputStream in = new ByteArrayInputStream(buffer);
				DataInputStream readIn = new DataInputStream(in);
				while (readIn.available() > 20) {
					Serializable data = null;
					int size = readIn.readInt();
					// Ommitting X symbol
					readIn.readChar();
					byte[] byteArray = new byte[size];
					readIn.read(byteArray);
					InputStream is = new ByteArrayInputStream(byteArray);
					ObjectInputStream ois = new ObjectInputStream(is);
					data = (Serializable) ois.readObject();
					ois.close();
					
					Serializable[] newArray = new Serializable[array.length + 1];
					System.arraycopy(array, 0, newArray, 0, array.length);
					newArray[array.length] = data;
					array = newArray;
				}
				readIn.close();
			} catch (IOException ex) {
				return null;
			} catch (ClassNotFoundException e) { 
				return null;
			}
			return array;
		}

		return null;
	}
}
